package com.cysoft.starter.log.core.repository.impl;

import com.alibaba.fastjson.JSON;
import com.cysoft.starter.log.core.model.LogInfo;
import com.cysoft.starter.log.core.properties.output.JdbcProperties;
import com.cysoft.starter.log.core.repository.DataRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author 玖零
 * @version v0.0.1
 * @project cysoft-spring-boot-starter-log
 * @package com.cysoft.starter.log.core.repository.impl
 * @date 2025-02-08 16:40
 * @desc jdbc日志存储实现类
 */
@Slf4j
public class JdbcRepository implements DataRepository {

    /**
     * Spring 的 JdbcTemplate，用于执行 JDBC 操作
     */
    private final JdbcTemplate jdbcTemplate;

    /**
     * JDBC 相关的配置信息
     */
    private final JdbcProperties jdbcProperties;

    /**
     * 构造函数，初始化 JdbcRepository 类的实例
     * @param jdbcTemplate     jdbc模板
     * @param jdbcProperties   jdbc配置
     */
    public JdbcRepository(JdbcTemplate jdbcTemplate, JdbcProperties jdbcProperties) {
        this.jdbcTemplate = jdbcTemplate;
        this.jdbcProperties = jdbcProperties;
    }

    /**
     * 实现 DataRepository 接口的 output 方法，用于将日志信息通过 JDBC 方式保存到数据库
     *
     * @param logInfo 要保存的日志信息对象
     */
    @Override
    public void output(LogInfo logInfo) {
        // 使用 debug 级别日志记录输出日志数据的开始信息，在生产环境可根据需要调整日志级别
        log.debug("本次请求 - 输出日志数据信息 - 开始");
        // 使用 debug 级别日志记录日志信息的详细内容
        log.debug("logInfo: {}", JSON.toJSONString(logInfo));
        // 使用 debug 级别日志记录输出日志数据的结束信息
        log.debug("本次请求 - 输出日志数据信息 - 结束");

        try {
            // 获取插入数据的 SQL 语句
            String insertSql = getInsertDataSql(jdbcProperties);
            // 组装插入语句所需的参数
            Object[] params = assembleParams(logInfo);
            // 使用 JdbcTemplate 执行插入操作
            jdbcTemplate.update(insertSql, params);
            // 使用 info 级别日志记录插入操作成功的信息
            log.info("日志信息插入数据库成功");
        } catch (Exception e) {
            // 捕获并使用 error 级别日志记录插入操作过程中可能出现的异常
            log.error("将日志信息插入数据库时发生异常", e);
        }
    }


    /**
     * 组装插入语句所需的参数
     *
     * @param logInfo 日志信息对象
     * @return 插入语句所需的参数数组
     */
    private Object[] assembleParams(LogInfo logInfo) {
        return new Object[] {
                logInfo.getId(),
                logInfo.getLogType(),
                logInfo.getRequestUrl(),
                logInfo.getRequestIp(),
                logInfo.getRequestHeader(),
                logInfo.getRequestBody(),
                logInfo.getResponseBody(),
                logInfo.getRequestResult(),
                logInfo.getErrorMessage(),
                LocalDateTime.now(),
                logInfo.getDuration(),
                logInfo.getPackageInfo(),
                logInfo.getClassInfo(),
                logInfo.getMethodInfo(),
                logInfo.getOperator(),
                logInfo.getRequestMethod()
        };
    }

    /**
     * 根据 JDBC 配置信息获取插入数据的 SQL 语句
     * @param jdbcProperties JDBC 相关的配置信息
     * @return 插入数据的 SQL 语句
     */
    private String getInsertDataSql(JdbcProperties jdbcProperties) {
        return Objects.nonNull(jdbcProperties.getInsertData())
                ? String.format(jdbcProperties.getInsertData(), jdbcProperties.getTableName())
                : String.format(jdbcProperties.getDataSourceEnum().getJdbcBase().getInsertData(), jdbcProperties.getTableName());
    }
}
